package top.scauwlt.provider.impl;

import lombok.extern.slf4j.Slf4j;
import top.scauwlt.config.RpcConfig;
import top.scauwlt.config.RpcServiceConfig;
import top.scauwlt.enums.RpcErrorMessageEnum;
import top.scauwlt.exception.RpcException;
import top.scauwlt.extension.ExtensionLoader;
import top.scauwlt.provider.ServiceProvider;
import top.scauwlt.registry.ServiceRegistry;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author wmm
 * @Date 2022/7/25 16:38
 */
@Slf4j
public class ServiceProviderImpl implements ServiceProvider {

    /**
     * key: interface name + group + version
     * value: service object
     */
    private final Map<String, Object> serviceMap;

    private final Set<String> registeredService;

    private final ServiceRegistry serviceRegistry;

    public ServiceProviderImpl() {
        serviceMap = new ConcurrentHashMap<>();
        registeredService = ConcurrentHashMap.newKeySet();
        serviceRegistry = ExtensionLoader.getExtensionLoader(ServiceRegistry.class).getExtension(RpcConfig.getInstance().getRegistryType());
    }

    @Override
    public void publishService(RpcServiceConfig rpcServiceConfig) {
        try {
            String host = InetAddress.getLocalHost().getHostAddress();
            String rpcServiceName = rpcServiceConfig.getRpcServiceName();
            serviceRegistry.registerService(rpcServiceName, new InetSocketAddress(host, RpcConfig.getInstance().getNettyPort()));
            serviceMap.put(rpcServiceName, rpcServiceConfig.getService());
            registeredService.add(rpcServiceName);
        } catch (UnknownHostException e) {
            log.error("publish service fail : ", e.getMessage());
        }
    }

    @Override
    public Object getService(String rpcServiceName) {
        Object service = serviceMap.get(rpcServiceName);
        if (service == null) {
            throw new RpcException(RpcErrorMessageEnum.SERVICE_CAN_NOT_BE_FOUND);
        }
        return service;
    }
}
